#include "FreeRTOS.h"
#include "semphr.h"
#include "hal_file.h"
#include "utils_file.h"
#include "utils_log.h"
#include "cJSON.h"

#define MAX_LOG_COUNT     (50)          //假设一条日志长度为64byte，则50*64=3200byte
#define LOG_FILE_PATH     "/log.txt"
#define MAX_BUFFER_LEN     (2048+256) 

static cJSON *g_objArray = NULL;
static uint32_t g_totalLogCount = 0;
SemaphoreHandle_t g_muxSem = NULL;

static int AddLogToJsonData(int curPos, const char *logStr, char *jsonLog, int logLen)
{
    if (NULL==logStr || NULL==jsonLog) {
        printf("[%s-%d]:input params is invalid\r\n",  __func__, __LINE__);
        return -1;
    }

    if (!cJSON_IsArray(g_objArray)) {
        g_objArray = cJSON_CreateArray();
        if(!cJSON_IsArray(g_objArray)){
            printf("[%s-%d]:cjson root creat error!\r\n",  __func__, __LINE__);
            return -1;
        }
    }

    if (g_totalLogCount >= MAX_LOG_COUNT) {//已超过日志总条数，则进行轮循替换
        cJSON_ReplaceItemInArray(g_objArray, curPos, cJSON_CreateString(logStr));
    } else {
        cJSON_AddItemToArray(g_objArray, cJSON_CreateString(logStr));
        g_totalLogCount++;
    }

    char *jsonStr = cJSON_PrintUnformatted(g_objArray);
    if (NULL == jsonStr){
        printf("[%s-%d]:cjson print unformatted error\r\n",  __func__, __LINE__);
        return -1;
    }
    int strLen = strlen(jsonStr);
    printf("[%s-%d]:cJSON_PrintUnformatted:%s, len:%d\r\n",  __func__, __LINE__, jsonStr, strlen(jsonStr), strLen);
    logLen = logLen > strLen ? strLen:logLen;
    memcpy(jsonLog, jsonStr, logLen);
    cJSON_free(jsonStr);
    return 0;
}

static cJSON  *GetJsonArrayFromFile()
{
    int fd = HalFileOpen(LOG_FILE_PATH, O_CREAT_FS|O_RDONLY_FS, 0);
    if (fd < 0){
        printf("[%s-%d]:open log file failed\n", __func__, __LINE__);
        return NULL;
    }
    
    char buf[MAX_BUFFER_LEN] = {0};
    int ret = HalFileRead(fd, buf, sizeof(buf));
    if (ret < 0){
       printf("[%s-%d]:read log file failed\n", __func__, __LINE__);
    }

    HalFileClose(fd);

    return cJSON_Parse(buf);
}

int ReadLogFromFile(char *jsonLog, int logLen)
{
    if (NULL == jsonLog){
        printf("[%s-%d]:input params is invalid\r\n",  __func__, __LINE__);
        return -1;
    }
    
    if(NULL == g_muxSem){
        g_muxSem = xSemaphoreCreateMutex();
        if (NULL == g_muxSem){
            printf("[%s-%d]:xSemaphoreCreateMutex create semMux failed\r\n",  __func__, __LINE__);
            return -1;
        }
    }

    xSemaphoreTake(g_muxSem, portMAX_DELAY);
    
    if (!cJSON_IsArray(g_objArray)){
        g_objArray = GetJsonArrayFromFile();
        if (!cJSON_IsArray(g_objArray)){
            printf("[%s-%d]:get json array from file failed\r\n",  __func__, __LINE__);
            xSemaphoreGive(g_muxSem);
            return -1;
        }
        g_totalLogCount = cJSON_GetArraySize(g_objArray);
    }

    char *jsonStr = cJSON_PrintUnformatted(g_objArray);
    if (NULL == jsonStr){
        printf("[%s-%d]:cjson print unformatted error\r\n",  __func__, __LINE__);
        xSemaphoreGive(g_muxSem);
        return -1;
    }
    xSemaphoreGive(g_muxSem);

    int strLen = strlen(jsonStr);
    printf("[%s-%d]:cJSON_PrintUnformatted:%s,len:%d\r\n",  __func__, __LINE__, jsonStr, strLen);
    logLen = logLen > strLen ? strLen:logLen;
    memcpy(jsonLog, jsonStr, logLen);
    cJSON_free(jsonStr);
    return 0;
}

int WriteLogToFile(const char *logStr)
{
    if (NULL == logStr){
        printf("[%s-%d]:input params is invalid\r\n",  __func__, __LINE__);
        return -1;
    }

    if(NULL == g_muxSem){
        g_muxSem = xSemaphoreCreateMutex();
        if (NULL == g_muxSem){
            printf("[%s-%d]:xSemaphoreCreateMutex create semMux failed\r\n",  __func__, __LINE__);
            return -1;
        }
    }

    xSemaphoreTake(g_muxSem, portMAX_DELAY);

    if (!cJSON_IsArray(g_objArray)){
        g_objArray = GetJsonArrayFromFile();
        if (!cJSON_IsArray(g_objArray)){
            printf("[%s-%d]:get json array from file failed\r\n",  __func__, __LINE__);    
        }else{
            g_totalLogCount = cJSON_GetArraySize(g_objArray);
        }
    }

    static uint32_t curPos = 0;
    char buf[MAX_BUFFER_LEN] = {0};
    int ret = AddLogToJsonData(curPos, logStr, buf, MAX_BUFFER_LEN);
    if (ret < 0){
        printf("[%s-%d]:add log to json data failed\r\n",  __func__, __LINE__);
        xSemaphoreGive(g_muxSem);
        return -1;
    }
    
    curPos++;
    if (curPos == g_totalLogCount) {
        curPos = 0;
    }

    int fd = HalFileOpen(LOG_FILE_PATH, O_CREAT_FS|O_RDWR_FS, 0);
    if (fd < 0){
        printf("[%s-%d]:open log file failed\n", __func__, __LINE__);
        xSemaphoreGive(g_muxSem);
        return -1;
    }

    ret = HalFileWrite(fd, buf, strlen(buf));
    if (ret < 0){
        printf("[%s-%d]:write log file failed\n", __func__, __LINE__);
    }
    HalFileClose(fd);
    xSemaphoreGive(g_muxSem);
    
    return ret;
}